using Godot;
using System;
using System.Collections.Generic;
using System.Linq;

public partial class UpgradeManager : Node
{
	// [Export]
	// public AbilityUpgrade[] upgradePool;
	[Export]
	ExperienceManager experienceManager;
	[Export]
	PackedScene upgradeScreen;

	GameEvents gameEvents;

	Dictionary<String,Upgrade> currentUpgrades = new Dictionary<string, Upgrade>();

	AbilityWeightedTable upgradePool = new AbilityWeightedTable();

	AbilityUpgrade upgradeAxe = GD.Load<AbilityUpgrade>("res://resource/upgrades/axe.tres");
	AbilityUpgrade upgradeAxeDamage = GD.Load<AbilityUpgrade>("res://resource/upgrades/axe_damage.tres");
	AbilityUpgrade upgradeSwordRate = GD.Load<AbilityUpgrade>("res://resource/upgrades/sword_rate.tres");
	AbilityUpgrade upgradeSwordDamage = GD.Load<AbilityUpgrade>("res://resource/upgrades/sword_damage.tres");
	AbilityUpgrade upgradePlayerSpeed = GD.Load<AbilityUpgrade>("res://resource/upgrades/player_speed.tres");

	public struct Upgrade{
		public AbilityUpgrade resource;
		public int quantity;

		public Upgrade(AbilityUpgrade resource,int quantity){
			this.resource = resource;
			this.quantity = quantity;
		}
	}


	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
		//添加技能
		upgradePool.AddItem(upgradeAxe,10);
		upgradePool.AddItem(upgradeSwordRate,10);
		upgradePool.AddItem(upgradeSwordDamage,10);
		upgradePool.AddItem(upgradePlayerSpeed,5);

		gameEvents = GetNode<GameEvents>("/root/GameEvents");
		experienceManager.LevelUp += OnLevelUp;
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _Process(double delta)
	{
	}


	//设置技能
	public void ApplyUpgrade(AbilityUpgrade abilityUpgrade){
		// Random rnd = new Random();
		// int index = rnd.Next(upgradePool.Length);
		// AbilityUpgrade chosenUpgrade = upgradePool[index];
		if(abilityUpgrade == null){
			return;
		}

		if(currentUpgrades.TryGetValue(abilityUpgrade.id,out Upgrade upgrade)){
			upgrade = currentUpgrades[abilityUpgrade.id];
			upgrade.quantity = upgrade.quantity +1;
			currentUpgrades[abilityUpgrade.id] = upgrade;
		}else{//没有此技能
			upgrade = new Upgrade(abilityUpgrade,1);
			currentUpgrades.Add(abilityUpgrade.id,upgrade);
		}
		// if(!currentUpgrades.ContainsKey(chosenUpgrade.id)){ 

		// 	Upgrade upgrade = new Upgrade(chosenUpgrade,1);
		// 	currentUpgrades.Add(chosenUpgrade.id,upgrade);
		// }else{
		// 	Upgrade upgrade = currentUpgrades[chosenUpgrade.id];
		// 	upgrade.quantity = upgrade.quantity +1;
		// 	currentUpgrades[chosenUpgrade.id] = upgrade;
		// }

		if(abilityUpgrade.maxQuantity>0){
			int currentQuantity = currentUpgrades[abilityUpgrade.id].quantity;
			if( currentQuantity == abilityUpgrade.maxQuantity){
				//技能数量等级到最顶了。移除技能池
				upgradePool.RemoveItem(abilityUpgrade);
			}
		}

		this.UpdateUpgradePool(abilityUpgrade);
		//TODO c#信号不能传递泛型或者复杂类，
		gameEvents.EmitAbilityUpgradeAdded(abilityUpgrade,currentUpgrades[abilityUpgrade.id].quantity);


		foreach (var kvp in currentUpgrades)
        {
            GD.Print($"技能id:{kvp.Key}；技能数量:{kvp.Value.quantity}");
        }
	}

	public void UpdateUpgradePool(AbilityUpgrade chosenUpgrade){
		if( chosenUpgrade.id == upgradeAxe.id){
			upgradePool.AddItem(upgradeAxeDamage,10);
		}
	}

	//随机选取技能
	public List<AbilityUpgrade> PickUpgrades(){
		List<AbilityUpgrade> chosenUpgrades = new List<AbilityUpgrade>();

		
		Random random = new Random();
		for(int i = 0;i<2;i++){
			if(upgradePool.items.Count == chosenUpgrades.Count ){
				break;
			}
			AbilityUpgrade chosenUpgrade = upgradePool.PickItem(chosenUpgrades);
			chosenUpgrades.Add(chosenUpgrade);
		}

		return chosenUpgrades;
	}

	public void OnUpgradeSelected(AbilityUpgrade upgrade){
		this.ApplyUpgrade(upgrade);
	}

	public void OnLevelUp(int newLevel){
		if(upgradePool == null || upgradePool.items.Count == 0){ //技能池为空
			return;
		}
		UpgradeScreen upgradeScreenInstantiate = upgradeScreen.Instantiate() as UpgradeScreen;
		AddChild(upgradeScreenInstantiate);

		upgradeScreenInstantiate.SetAbilityUpgrades(this.PickUpgrades());
		upgradeScreenInstantiate.UpgradeSelected += OnUpgradeSelected;
	}
}
